//
//  CameraViewController.swift
//  JJImagePicker
//
//  Created by 李加建 on 2021/6/2.
//

import AVFoundation
import UIKit

class CameraViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
        setNavi()
        setCamera()
    }

    var manager: ImagePickerManager

    init(manager: ImagePickerManager) {
        self.manager = manager
        super.init(nibName: nil, bundle: nil)
    }

    @available(*, unavailable)
    required init?(coder _: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    lazy var session: AVCaptureSession = {
        let lazy = AVCaptureSession()
        lazy.sessionPreset = .photo
        return lazy
    }()

    lazy var middleView: UIView = {
        let lazy = UIView()
        lazy.backgroundColor = .clear
        return lazy
    }()

    lazy var backgroundButton: UIButton = {
        let lazy = UIButton(frame: view.bounds)
        return lazy
    }()

    lazy var takePhotoButton: UIButton = {
        let lazy = UIButton(frame: CGRect(x: 0, y: 0, width: 72, height: 72))
        lazy.backgroundColor = .clear
        lazy.addTarget(self, action: #selector(takePhoto), for: .touchUpInside)
        lazy.layer.borderWidth = 5
        lazy.layer.borderColor = UIColor.white.cgColor
        lazy.clipsToBounds = true
        lazy.layer.cornerRadius = 36

        let layer = CALayer()
        layer.backgroundColor = UIColor.white.cgColor
        layer.frame = CGRect(x: 8, y: 8, width: 56, height: 56)
        layer.cornerRadius = 28
        lazy.layer.addSublayer(layer)

        return lazy
    }()

    lazy var tipLabel: UILabel = {
        let lazy = UILabel(frame: .zero)
        lazy.text = "照片"
        lazy.textColor = UIColor(red: 243.0 / 255.0, green: 210.0 / 255.0, blue: 73.0 / 255.0, alpha: 1)
        lazy.font = UIFont.systemFont(ofSize: 15)
        return lazy
    }()

    lazy var backButton: UIButton = {
        let lazy = UIButton(frame: .zero)
        lazy.setTitle("取消", for: .normal)
        lazy.setTitleColor(.white, for: .normal)
        lazy.addTarget(self, action: #selector(backItemAction), for: .touchUpInside)
        return lazy
    }()

    lazy var changeButton: UIButton = {
        let lazy = UIButton(frame: .zero)
        lazy.setTitleColor(.white, for: .normal)
        lazy.addTarget(self, action: #selector(changeButtonAction), for: .touchUpInside)
        lazy.backgroundColor = UIColor(red: 28.0 / 255.0, green: 28.0 / 255.0, blue: 28.0 / 255.0, alpha: 1)
        lazy.layer.cornerRadius = 24
        lazy.clipsToBounds = true
        let image = UIImage.createImage(base64String: refreshBase64String)
        lazy.setImage(image, for: .normal)
        lazy.setImage(image, for: .highlighted)
        return lazy
    }()

    var device: AVCaptureDevice?
    var input: AVCaptureDeviceInput?
    var output: AVCapturePhotoOutput?
    var connection: AVCaptureConnection?
    var preViewLayer: AVCaptureVideoPreviewLayer?

    override var preferredStatusBarStyle: UIStatusBarStyle {
        .lightContent
    }

    override func viewSafeAreaInsetsDidChange() {
        super.viewSafeAreaInsetsDidChange()
        updateSafeArea()
    }
}

extension CameraViewController {
    func setup() {
        backgroundButton.backgroundColor = .black
        view.addSubview(backgroundButton)
        view.addSubview(middleView)
        view.addSubview(takePhotoButton)
        view.addSubview(backButton)
        view.addSubview(changeButton)
        view.addSubview(tipLabel)
    }

    func updateSafeArea() {
        middleView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.width * (4.0 / 3.0))
        preViewLayer?.frame = middleView.bounds
        middleView.center = CGPoint(x: view.center.x, y: view.center.y - 56)
        takePhotoButton.frame = CGRect(x: 0, y: 0, width: 72, height: 72)
        let pointY = middleView.frame.maxY + 94
        takePhotoButton.center = CGPoint(x: view.center.x, y: pointY)

        backButton.frame = CGRect(x: 0, y: 0, width: 80, height: 32)
        backButton.center = CGPoint(x: 60, y: takePhotoButton.center.y)
        changeButton.frame = CGRect(x: 0, y: 0, width: 48, height: 48)
        changeButton.center = CGPoint(x: view.frame.width - 44, y: takePhotoButton.center.y)

        tipLabel.sizeToFit()
        tipLabel.center = CGPoint(x: takePhotoButton.center.x, y: takePhotoButton.center.y - 66)
    }

    func setNavi() {
        let attributes: [NSAttributedString.Key: Any] = [
            NSAttributedString.Key.foregroundColor: UIColor.black,
            NSAttributedString.Key.font: UIFont(name: "PingFangSC-Semibold", size: 18) as Any,
        ]
        navigationController?.navigationBar.titleTextAttributes = attributes
        let image = UIImage.createImage(color: .clear, size: CGSize(width: 44, height: 44))
        navigationController?.navigationBar.isTranslucent = true
        navigationController?.navigationBar.setBackgroundImage(image, for: .default)
        navigationController?.navigationBar.shadowImage = UIImage()
        navigationController?.navigationBar.backgroundColor = .clear

//        let backItem = UIBarButtonItem(title: "", style: .done, target: self, action: #selector(backItemAction))
//        backItem.tintColor = .white
//        navigationItem.leftBarButtonItem = backItem
    }

    @objc
    func backItemAction() {
        dismiss(animated: true, completion: nil)
    }

    @objc
    func changeButtonAction() {
        guard let device = self.device else { return }
        if device.position == AVCaptureDevice.Position.front {
            self.device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)

        } else if device.position == AVCaptureDevice.Position.back {
            self.device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front)
        }

        guard let change = self.device else { return }
        if let input = self.input {
            session.removeInput(input)
        }
        input = try? AVCaptureDeviceInput(device: change)
        if let input = self.input {
            if session.canAddInput(input) {
                session.addInput(input)
            }
        }
        session.beginConfiguration()
        session.commitConfiguration()
        session.startRunning()
    }

    func setCamera() {
        self.device = AVCaptureDevice.default(for: .video)

        guard let device = self.device else { return }
        input = try? AVCaptureDeviceInput(device: device)
        if let input = self.input {
            if session.canAddInput(input) {
                session.addInput(input)
            }
        }

        let output = AVCapturePhotoOutput()
        self.output = output
        if session.canAddOutput(output) {
            session.addOutput(output)
        }

        preViewLayer = AVCaptureVideoPreviewLayer(session: session)
        preViewLayer?.videoGravity = .resizeAspectFill
        if let preLayer = preViewLayer {
            middleView.layer.addSublayer(preLayer)
        }

        session.beginConfiguration()
        session.commitConfiguration()
        session.startRunning()
    }

    @objc
    func takePhoto() {
        let settings = AVCapturePhotoSettings(rawPixelFormatType: .min)
        output?.capturePhoto(with: settings, delegate: self)
    }
}

extension CameraViewController: AVCapturePhotoCaptureDelegate {
    func photoOutput(_: AVCapturePhotoOutput, willCapturePhotoFor _: AVCaptureResolvedPhotoSettings) {}

    func photoOutput(_: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error _: Error?) {
        if let data = photo.fileDataRepresentation(), let image = UIImage(data: data)?.fixOrientation() {
            if manager.allowsEditing {
                manager.editImage = image
                let next = ImageCutController(manager: manager)
                navigationController?.pushViewController(next, animated: true)
            } else {
                manager.delegate?.didSeletedImage(image)
            }
        }
    }
}

extension UIImage {
    func fixOrientation() -> UIImage? {
        guard let cgImage = self.cgImage else { return nil }
        var transform: CGAffineTransform = .identity

        transform = transform.translatedBy(x: 0, y: size.height)
        transform = transform.rotated(by: -CGFloat.pi / 2)
        transform = transform.translatedBy(x: size.width, y: 0)
        transform = transform.scaledBy(x: -1, y: 1)

        UIGraphicsBeginImageContext(size)
        let context = UIGraphicsGetCurrentContext()
        context?.concatenate(transform)
        let pointY = size.height - size.width
        context?.draw(cgImage, in: CGRect(origin: CGPoint(x: -pointY, y: 0), size: CGSize(width: size.height, height: size.width)))
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}
